package com.zx.template.base;

/**
 * @author szh
 * @date 2022/8/3 14:15
 */

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

import java.beans.PropertyDescriptor;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * describe:
 **/
public class BeanCopyUtils {

    public static String[] getNullPropertyNames(Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        PropertyDescriptor[] pds = src.getPropertyDescriptors();

        Set<String> emptyNames = new HashSet<>();
        for (PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null) {
                emptyNames.add(pd.getName());
            }
        }
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }

    public static <E, T> T copyPropertiesIgnoreNull(E src, T target) {
        if (target == null) {
            return null;
        }
        BeanUtils.copyProperties(src, target, getNullPropertyNames(src));
        return target;
    }

    public static <T> T convertBean(Object object, Class<T> entityClass) {
        if (null == object) {
            return null;
        }
        return JSONUtil.toBean(JSONUtil.toJsonStr(object), entityClass);
    }

    public static <E, T> List<E> convertList(List<T> list, Class<E> entityClass) {
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        return list.stream().map(item -> convertBean(item, entityClass)).collect(Collectors.toList());
    }

    public static <E, T> PageBean<E> convertPage(IPage<T> page, Class<E> entityClass) {
        List<T> list = page.getRecords();
        List<E> collect = list.stream().map(item -> convertBean(item, entityClass)).collect(Collectors.toList());
        return PageBean.<E>builder().current((int) page.getCurrent()).size((int) page.getSize()).total((int) page.getTotal()).content(collect).build();
    }

    public static Map convertBeanToMap(Object object) {
        return convertBean(object, Map.class);
    }

    public static <E, T> T copyProperties(E src, T target) {
        BeanUtils.copyProperties(src, target);
        return target;
    }

    private static String[] getNullAndIdPropertyNames(Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        PropertyDescriptor[] pds = src.getPropertyDescriptors();

        Set<String> emptyNames = new HashSet<>();
        for (PropertyDescriptor pd : pds) {
            if (pd.getName().equals("id"))
                emptyNames.add(pd.getName());
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null) {
                emptyNames.add(pd.getName());
            }
        }
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }

    public static <E, T> T copyPropertiesIgnoreNullAndId(E src, T target) {
        if (target == null) {
            return null;
        }
        BeanUtils.copyProperties(src, target, getNullAndIdPropertyNames(src));
        return target;
    }

}
